#include <iostream>
#include <cstring>
#include <unistd.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/syscall.h> // 仅仅是了解
using namespace std;


//  __thread int global_value = 100;

// void *startRoutine(void *args)
// {
//      //pthread_detach(pthread_self());
//      //cout << "线程分离....." << endl;
//     while (true)
//     {
//         // 临界区，不是所有的线程代码都是临界区
//         cout << "thread " << pthread_self() << " global_value: "
//              << global_value << " &global_value: " << &global_value
//              << " Inc: " << global_value++ << " lwp: " << ::syscall(SYS_gettid)<<endl;
//         sleep(1);
//         break;
//     }
//     // 退出进程，任何一个线程调用exit，都表示整个进程退出
//     //exit(1);
//     // pthread_exit()
// }


// int 票数计数器
// 临界资源
int tickets = 10000; // 临界资源，可能会因为共同访问，可能会造成数据不一致问题。
pthread_mutex_t mutex;

void *getTickets(void *args)
{
    const char *name = static_cast<const char *>(args);

    while (true)
    {
        // 临界区,只要对临界区加锁，而且加锁的粒度约细越好
        // 加锁的本质是让线程执行临界区代码串行化
        // 加锁是一套规范，通过临界区对临界资源进行访问的时候，要加就都要加
        // 锁保护的是临界区, 任何线程执行临界区代码访问临界资源，都必须先申请锁，前提是都必须先看到锁！
        // 这把锁，本身不就也是临界资源吗？锁的设计者早就想到了
        // pthread_mutex_lock: 竞争和申请锁的过程，就是原子的！
        // 难道在加锁的临界区里面，就没有线程切换了吗？？？？
        pthread_mutex_lock(&mutex);
        if (tickets > 0)
        {
            usleep(1000);
            cout << name << " 抢到了票, 票的编号: " << tickets << endl;
            tickets--;
            pthread_mutex_unlock(&mutex);

            //other code
            //usleep(123); //模拟其他业务逻辑的执行
        }
        else
        {
            // 票抢到几张，就算没有了呢？0
            cout << name << "] 已经放弃抢票了，因为没有了..." << endl;
            pthread_mutex_unlock(&mutex);
            break;
        }
    }

    return nullptr;
}

// 如何理解exit？
int main()
{
    pthread_mutex_init(&mutex, nullptr);
    pthread_t tid1;
    pthread_t tid2;
    pthread_t tid3;
    pthread_t tid4;
    // pthread_create(&tid1, nullptr, startRoutine, (void *)"thread 1");
    // pthread_create(&tid1, nullptr, startRoutine, (void *)"thread 2");
    // pthread_create(&tid1, nullptr, startRoutine, (void *)"thread 3");
    // pthread_create(&tid1, nullptr, startRoutine, (void *)"thread 4");


    pthread_create(&tid2, nullptr, getTickets, (void *)"thread 1");
    pthread_create(&tid2, nullptr, getTickets, (void *)"thread 2");
    pthread_create(&tid3, nullptr, getTickets, (void *)"thread 3");
    pthread_create(&tid4, nullptr, getTickets, (void *)"thread 4");

    // sleep(1);
    // 倾向于：让主线程，分离其他线程

    // pthread_detach(tid1);
    // pthread_detach(tid2);
    // pthread_detach(tid3);

    // 1. 立即分离,延后分离 -- 线程活着 -- 意味着，我们不在关心这个线程的死活。线程退出的第四种方式，延后退出
    // 2. 新线程分离，但是主线程先退出(进程退出) --- 一般我们分离线程，对应的main thread一般不要退出(常驻内存的进程)
     //sleep(1);

    int n = pthread_join(tid1, nullptr);
    cout << n << ":" << strerror(n) << endl;
    n = pthread_join(tid2, nullptr);
    cout << n << ":" << strerror(n) << endl;
    n = pthread_join(tid3, nullptr);
    cout << n << ":" << strerror(n) << endl;
    n = pthread_join(tid4, nullptr);
    cout << n << ":" << strerror(n) << endl;

    pthread_mutex_destroy(&mutex);

    return 0;
}